上一篇介紹了如何從Multi-frame Dicom取出圖片,今天要來跟大家分享如何用圖片合成出dicom檔。
首先一樣需要import一些dependency
<!-- <!– https://mvnrepository.com/artifact/dcm4che/dcm4che –>-->
<dependency>
<groupId>dcm4che</groupId>
<artifactId>dcm4che</artifactId>
<version>2.0.29</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-core -->
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-core</artifactId>
<version>5.22.4</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-imageio -->
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-imageio</artifactId>
<version>5.22.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dcm4che.tool/dcm4che-tool-common -->
<dependency>
<groupId>org.dcm4che.tool</groupId>
<artifactId>dcm4che-tool-common</artifactId>
<version>5.22.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-image -->
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-image</artifactId>
<version>5.22.4</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-imageio-opencv</artifactId>
<version>5.22.4</version>
</dependency>
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-imageio-rle</artifactId>
<version>5.22.4</version>
<scope>runtime</scope>
</dependency>
>
<!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-json -->
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-json</artifactId>
<version>5.22.4</version>
</dependency>
範例程式如下
public static void main(String[] args) throws Exception {
int BUFFER_SIZE = 8162;
byte[] buf = new byte[BUFFER_SIZE];
ElementDictionary DICT = ElementDictionary.getStandardElementDictionary();
int[] TYPE2_TAGS = {
Tag.ContentDate,
Tag.ContentTime
};
// new 一個attribute(dicom的描述資訊)
Attributes fileMetadata = new Attributes();
fileMetadata.setString(Tag.StudyInstanceUID, VR.UI, UIDUtils.createUID());
fileMetadata.setString(Tag.SeriesInstanceUID, VR.UI, UIDUtils.createUID());
fileMetadata.setString(Tag.SOPInstanceUID, VR.UI, UIDUtils.createUID());
// =====插入資訊=====
// patient info
setMetadata(fileMetadata, Tag.PatientName, "Test Patient");
setMetadata(fileMetadata, Tag.PatientID, "11311313");
setMetadata(fileMetadata, Tag.PatientSex, "M");
setMetadata(fileMetadata, Tag.PatientAge, "26Y");
setMetadata(fileMetadata, Tag.PatientBirthDate, "19500101");
// study info
setMetadata(fileMetadata, Tag.StudyDate, "20240920");
setMetadata(fileMetadata, Tag.StudyTime, "0:00:00");
setMetadata(fileMetadata, Tag.StudyDescription, "Study Description");
setMetadata(fileMetadata, Tag.StudyID, "123");
setMetadata(fileMetadata, Tag.SOPClassUID, UID.SecondaryCaptureImageStorage);
supplementType2Tags(fileMetadata);
fileMetadata.setInt(Tag.NumberOfFrames, VR.IS, 1);
fileMetadata.setInt(Tag.SeriesNumber, VR.IS, 2);
// =====插入資訊結束=====
Path imagePath= Paths.get("C:\\Users\\kris\\Downloads\\dcm\\test.jpg");
Path dicomPath= Paths.get("C:\\Users\\kris\\Downloads\\dcm\\ttest.dcm");
fileMetadata.trimToSize();
// 印出完整的Attribute
System.out.println(fileMetadata);
// 寫出dicom
try (SeekableByteChannel channel = Files.newByteChannel(imagePath);
DicomOutputStream dos = new DicomOutputStream(dicomPath.toFile())) {
XPEGParser parser = new JPEGParser(channel);
parser.getAttributes(fileMetadata);
dos.writeDataset(fileMetadata.createFileMetaInformation(parser.getTransferSyntaxUID()), fileMetadata);
dos.writeHeader(Tag.PixelData, VR.OB, -1);
dos.writeHeader(Tag.Item, null, 0);
// 這是single-frame dicom的寫法,如果要寫成multi-frame dicom,
// 需要重複執行copyPixelData function即可,不過要注意每張圖片的大小都要一樣
// 如以下範例,多執行一次copyPixelData function(輸入不同的SeekableByteChannel) 即可合成multi-frame dicom
// copyPixelData(channel1, parser.getCodeStreamPosition(), dos);
copyPixelData(channel, parser.getCodeStreamPosition(), dos);
dos.writeHeader(Tag.SequenceDelimitationItem, null, 0);
System.out.println("converted");
}
}
public static void copyPixelData(SeekableByteChannel channel, long position, DicomOutputStream dos, byte... prefix)
throws IOException {
long codeStreamSize = channel.size() - position + prefix.length;
dos.writeHeader(Tag.Item, null, (int) ((codeStreamSize + 1) & ~1));
dos.write(prefix);
channel.position(position);
copy(channel, dos);
if ((codeStreamSize & 1) != 0)
dos.write(0);
}
private static void copy(ByteChannel in, OutputStream out) throws IOException {
ByteBuffer bb = ByteBuffer.wrap(buf);
int read;
while ((read = in.read(bb)) > 0) {
out.write(buf, 0, read);
bb.clear();
}
}
public static void setMetadata(Attributes metadata, int tag, String value) {
if (value != null)
metadata.setString(tag, DICT.vrOf(tag), value);
}
private static void supplementType2Tags(Attributes metadata) {
for (int tag : TYPE2_TAGS)
if (!metadata.contains(tag))
metadata.setNull(tag, DICT.vrOf(tag));
}
執行main function後就可以生成dicom檔案了!
以上是關於如何用圖片(jpg)合成出dicom檔的教學文章,希望對大家有幫助!!!